package com.aidex.system.service.impl;

import com.aidex.common.core.service.BaseServiceImpl;
import com.aidex.common.utils.StringUtils;
import com.aidex.system.domain.*;
import com.aidex.system.mapper.VInternationalAsdMapper;
import com.aidex.system.service.*;
import com.github.pagehelper.PageInfo;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import org.apache.lucene.search.spell.NGramDistance;
import org.apache.lucene.search.spell.StringDistance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 国际申报数据Service业务层处理
 * @author wll
 * @email wll
 * @date 2021-10-14
 */
@Service
@Transactional(readOnly = false)
public class VInternationalAsdServiceImpl extends BaseServiceImpl<VInternationalAsdMapper, VInternationalAsd> implements VInternationalAsdService
{
    private static final Logger log = LoggerFactory.getLogger(VInternationalAsdServiceImpl.class);

    @Autowired
    private CargoDetailService cargoDetailService;
    @Autowired
    private NlpService nlpService;
    @Autowired
    private OptimizationSuggestionRuleService optimizationSuggestionRuleService;
    @Autowired
    private RiskGoodsNameKeySuggestService riskGoodsNameKeySuggestService;
    @Autowired
    private VCsisBusinessAsdService vCsisBusinessAsdService;
    @Autowired
    private VInternationalUnpackingService vInternationalUnpackingService;
    @Autowired
    private VCsisBusinessUnpackingService vCsisBusinessUnpackingService;
    @Autowired
    private WordMatchTimeService wordMatchTimeService;
    @Autowired
    private RunLogService runLogService;
    @Autowired
    private ApiLogService apiLogService;
    @Value("${wxp.path}")
    private String wxpPath;

    /**
     * 获取单条数据
     * @param vInternationalAsd 国际申报数据
     * @return 国际申报数据
     */
    @Override
    public VInternationalAsd get(VInternationalAsd vInternationalAsd)
    {
        VInternationalAsd dto = super.get(vInternationalAsd);
        return dto;
    }

    /**
     * 获取单条数据
     * @param id 国际申报数据id
     * @return 国际申报数据
     */
    @Override
    public VInternationalAsd get(String id)
    {
        VInternationalAsd dto = super.get(id);
        return dto;
    }


    /**
     * 查询国际申报数据列表
     * @param vInternationalAsd 国际申报数据
     * @return 国际申报数据
     */
    @Override
    public List<VInternationalAsd> findList(VInternationalAsd vInternationalAsd)
    {
        return super.findList(vInternationalAsd);
    }

    /**
     * 分页查询国际申报数据列表
     * @param vInternationalAsd 国际申报数据
     * @return 国际申报数据
     */
    @Override
    public PageInfo<VInternationalAsd> findPage(VInternationalAsd vInternationalAsd)
    {
        return super.findPage(vInternationalAsd);
    }

    /**
     * 保存国际申报数据
     * @param vInternationalAsd
     * @return 结果
     */
    @Override
    public boolean save(VInternationalAsd vInternationalAsd)
    {
        vInternationalAsd.setStatus(0);
        return super.save(vInternationalAsd);
    }


    /**
     * 删除国际申报数据信息
     * @param vInternationalAsd
     * @return 结果
     */
    @Override
    public boolean remove(VInternationalAsd vInternationalAsd)
    {
        return super.remove(vInternationalAsd);
    }

    /**
     * 批量删除国际申报数据
     * @param ids 需要删除的国际申报数据ID
     * @return 结果
     */
    @Transactional(readOnly = false)
    @Override
    public int deleteVInternationalAsdByIds(String[] ids)
    {
        return mapper.deleteVInternationalAsdByIds(ids);
    }

    @Override
    @Transactional(readOnly = false)
    public void handleBatchWaybill(Integer limit) {
        StringDistance distance = new NGramDistance();
        // 获取配置信息
        OptimizationSuggestionRule rule = optimizationSuggestionRuleService.getRule();
        if (rule == null) {
            runLogService.saveError("没有获取到优化建议规则设置","发生错误");
            log.error("没有获取到优化建议规则设置");
            return;
        }
        // 获取x光难以识别清单
        CargoDetail param = new CargoDetail();
        param.setType(1);
        List<CargoDetail> list = cargoDetailService.findList(param);
        // 获取隐含性危险品清单
        List<String> wxList = this.getWxp();
        // 处理国际航班历史数据
        List<VInternationalAsd> billList = mapper.getUnHandleBillList(limit);
        for (VInternationalAsd row : billList) {
            this.handle(row.getCargodesc(), list, wxList, rule, distance, 2, row.getAwbno());
            row.setStatus(1);
            mapper.update(row);
        }
        // 处理国内航班历史数据
        List<VCsisBusinessAsd> asds = vCsisBusinessAsdService.getUnHandleBillList(limit);
        for (VCsisBusinessAsd row : asds) {
            this.handle(row.getCargodesc(), list, wxList, rule, distance, 1, row.getAwbno());
            row.setStatus(1);
            vCsisBusinessAsdService.update(row);
        }
    }

    /**
     * 执行比对
     *
     * @param cargoDesc
     * @param list
     * @param wxList
     * @param rule
     * @param distance
     * @param type 1 国内 2 国际
     */
    private void handle(String cargoDesc, List<CargoDetail> list, List<String> wxList, OptimizationSuggestionRule rule,
                        StringDistance distance, Integer type, String no) {

        if (StringUtils.isBlank(cargoDesc)) {
            return;
        }
        // 获取开箱结果
        // 首先获取开箱数据
        String info = "";
        BigDecimal res = BigDecimal.ZERO;
        Boolean isDangerous = Boolean.FALSE;
        if (type == 1) {
            // 国内 T放行 O移交 R拒运
            VCsisBusinessUnpacking byWaybillNo = vCsisBusinessUnpackingService.getByWaybillNo(no);
            if (byWaybillNo != null) {
                info = byWaybillNo.getCargoname();
                switch (byWaybillNo.getResult()) {
                    case "O":
                        res = BigDecimal.valueOf(5d / 7 * 100);
                        break;
                    case "R":
                        res = BigDecimal.valueOf(3d / 7 * 100);
                        break;
                    default:
                        res = BigDecimal.valueOf(1d / 7 * 100);
                }
            }
        } else {
            VInternationalUnpacking b = vInternationalUnpackingService.getByWaybillNo(no);
            if (b != null) {
                info = b.getCargoname();
                switch (b.getResult()) {
                    case "移交":
                        res = BigDecimal.valueOf(5d / 7 * 100);
                        break;
                    case "拒运":
                        res = BigDecimal.valueOf(3d / 7 * 100);
                        break;
                    default:
                        res = BigDecimal.valueOf(1d / 7 * 100);
                }
            }
        }
        if (res.compareTo(rule.getDangerousLimit()) >= 0) {
            isDangerous = Boolean.TRUE;
        }
        /**
         * 1、分词
         * 2、判断是否存在三个清单中，如果是，直接结束
         * 3、判断是否在优化建议清单中，如果是，直接结束
         * 4、进行难以通过x光机的货品清单语义对比，如果满足条件，推送到优化建议清单并结束
         * 5、与隐含性危险品名库进行语义对比，如果满足条件，推送到优化建议清单并结束
         * 6、根据开箱次数、代理人诚信等级、计算风险程度
         */
        List<String> words = nlpService.getCutList(cargoDesc);
        for (String word : words) {
            CargoDetail cargoDetail = cargoDetailService.getByName(word);
            if (cargoDetail != null) {
                continue;
            }
            RiskGoodsNameKeySuggest suggest = riskGoodsNameKeySuggestService.getByName(word);
            if (suggest != null) {
                continue;
            }
            Boolean isContinue = Boolean.FALSE;
            // 匹配x光机难以通过值
            for (CargoDetail detail : list) {
                BigDecimal xrayLimit = rule.getXrayLimit();
                BigDecimal targetLike = BigDecimal.valueOf(distance.getDistance(detail.getKeywords(), word) * 100);
                if (targetLike.compareTo(xrayLimit) >= 0) {
                    // 添加至建议清单
                    riskGoodsNameKeySuggestService.addSuggest(word, 1);
                    isContinue = Boolean.TRUE;
                    break;
                }
            }
            if (isContinue) {
                continue;
            }
            // 和隐含性危险品名库进行比对
            for (String pm : wxList) {
                BigDecimal riskLimit = rule.getRiskLimit();
                BigDecimal targetLike = BigDecimal.valueOf(distance.getDistance(pm, word) * 100);
                if (targetLike.compareTo(riskLimit) >= 0 && wordMatchTimeService.checkWord(word, rule.getRiskMatchTime())) {
                    // 添加至建议清单
                    riskGoodsNameKeySuggestService.addSuggest(word, 3);
                    isContinue = Boolean.TRUE;
                    break;
                }
            }
            if (isContinue) {
                continue;
            }
            // 计算风险度
            if (isDangerous) {
                if (StringUtils.isBlank(info) || info.contains(word)) {
                    riskGoodsNameKeySuggestService.addSuggest(word, 2);
                }
            }
        }
    }

    /**
     * 获取危险品名库
     *
     * @return
     */
    private List<String> getWxp() {
//        List<String> list = new ArrayList<>();
//        try {
//            LineIterator iterator = FileUtils.lineIterator(new File(wxpPath), "UTF-8");
//            while(iterator.hasNext()) {
//                list.add(iterator.nextLine());
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        return list;
        CargoDetail param = new CargoDetail();
        param.setType(3);
        List<CargoDetail> list = cargoDetailService.findList(param);
        return list.stream().map(CargoDetail::getKeywords).collect(Collectors.toList());
    }

}
